################################################################################
#
#Copyright (c) 2012, Petr Skramovsky
#All rights reserved.
#
#Redistribution and use in source and binary forms, with or without
#modification, are permitted provided that the following conditions are met:
#    * Redistributions of source code must retain the above copyright
#      notice, this list of conditions and the following disclaimer.
#    * Redistributions in binary form must reproduce the above copyright
#      notice, this list of conditions and the following disclaimer in the
#      documentation and/or other materials provided with the distribution.
#
#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
#ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
#WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
#DISCLAIMED. IN NO EVENT SHALL Petr Skramovsky BE LIABLE FOR ANY
#DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
#(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
#LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
#ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
#(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
#SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
################################################################################

import c4d
import c4d.utils
import os
import md3
import math
from qsystem import QFileSystem

PLA_COMMAND = 12421
IMG_EXTS = [ ".jpg", ".jpeg", ".png", ".tga" ]

def md3_make_material(doc,fs,tex):
  name = tex.split("/")[-1]
  if doc.SearchMaterial(name):
    return doc.SearchMaterial(name)
  rname = tex.split(".")[0]
  fex = ""
  for ex in IMG_EXTS:
    if fs[ rname + ex ]:
      fex = ex
      break
  epath = os.path.join( doc.GetDocumentPath(), rname.replace("/","\\") + ex )
  fs.extract( rname + ex, doc.GetDocumentPath() )
  mat = c4d.BaseMaterial(c4d.Mmaterial)
  shd = c4d.BaseList2D(c4d.Xbitmap)
  shd[c4d.BITMAPSHADER_FILENAME] = epath
  mat[c4d.MATERIAL_COLOR_SHADER] = shd
  mat[c4d.MATERIAL_USE_SPECULAR] = False
  mat.SetName(name)
  mat.InsertShader(shd)
  mat.Message(c4d.MSG_UPDATE)
  mat.Update(True, True)
  return mat

def c4d_make_model(doc,fs,name,skincolor="default"):
    m = fs[name]
    if not m:
        return
    
    skin = fs[name.split(".")[0] + "_" + skincolor + ".skin"]
    skin_tex = {}
    if skin:
        sp = skin.split()
        for i in range(0,m.num_surfaces):
            s, t = sp[i].split(",")
            skin_tex[s] = t
    
    root_object = c4d.BaseObject(c4d.Onull)
    root_object.SetName(name)
    root_object.SetAbsRot(c4d.Vector(0,math.pi/2,0))
  
    ps = []
    for s in m.surfaces:
        p = c4d.PolygonObject(s.num_verts, s.num_triangles)
        p.SetName(s.name)
        uv = c4d.UVWTag(s.num_triangles)
        uv[c4d.UVWTAG_LOCK] = True
        p.SetPhong(True, 1, math.radians(80.0))
        p.InsertTag(uv)

        if skin:
            tex = skin_tex[s.name]
        else:
            tex = s.shaders[0].name
        #tex = s.shaders[0].name
        mat = md3_make_material(doc,fs,tex)
        doc.InsertMaterial(mat)
        mtag = c4d.TextureTag()
        mtag.SetMaterial(mat)
        mtag[c4d.TEXTURETAG_PROJECTION] = c4d.TEXTURETAG_PROJECTION_UVW
        p.InsertTag(mtag)
        
        for i in range(s.num_triangles):
            t = s.triangles[i]
            p.SetPolygon(i, c4d.CPolygon(t.a,t.b,t.c))
            uv.SetSlow(i, c4d.Vector(s.st[t.a].s, s.st[t.a].t, 0), c4d.Vector(s.st[t.b].s, s.st[t.b].t, 0), c4d.Vector(s.st[t.c].s, s.st[t.c].t, 0), c4d.Vector())
                
        p.InsertUnder(root_object)
        ps.append(p)
    
    doc.InsertObject(root_object)
    
    if not c4d.IsCommandChecked(PLA_COMMAND):
        c4d.CallCommand(PLA_COMMAND)
    pi = 0
    for s in m.surfaces:
        doc.SetActiveObject(ps[pi])
        for fi in range(0, s.num_frames):
            for i in range(0, s.num_verts):
                ps[pi].SetPoint(i, c4d.Vector(s.vertexes[fi][i].x, s.vertexes[fi][i].y, s.vertexes[fi][i].z))
            doc.SetTime( c4d.BaseTime( fi, 30 ) )
            c4d.CallCommand( 12410 )
        pi += 1
        
    for i in range(0,m.num_tags):
        tag = m.tags[i]
        tag_object = c4d.BaseObject(c4d.Onull)
        tag_object.SetName(tag.name)
        tag_object.InsertUnder(root_object)
        doc.SetActiveObject(tag_object)
        for fi in range(0, m.num_frames):
            tag = m.tags[fi*m.num_tags +i]
            tag_object.SetAbsPos(c4d.Vector(tag.origin.x,tag.origin.y,tag.origin.z))
            tag_object.SetAbsRot(c4d_matrix_hpb(tag.axis))
            doc.SetTime( c4d.BaseTime( fi, 30 ) )
            c4d.CallCommand( 12410 )
    return root_object

def c4d_find_child(base,child):
    for o in base.GetChildren():
        if child == o.GetName():
            return o
    return None

def c4d_make_const(src,target):
    const = c4d.BaseTag(1019364)
    const[c4d.ID_CA_CONSTRAINT_TAG_PSR] = 1
    const[10001] = target
    src.InsertTag(const)
    
def c4d_make_player(doc,fs,name,weapname,skincolor="default"):
    root_object = c4d.BaseObject(c4d.Onull)
    root_object.SetName(name)
    weap = c4d_make_model(doc,fs,weapname)
    head = c4d_make_model(doc,fs,name+"/head.md3",skincolor)
    upper = c4d_make_model(doc,fs,name+"/upper.md3",skincolor)
    lower = c4d_make_model(doc,fs,name+"/lower.md3",skincolor)
    c4d_make_const(head,c4d_find_child(upper,"tag_head"))
    c4d_make_const(upper,c4d_find_child(lower,"tag_torso"))
    c4d_make_const(weap,c4d_find_child(upper,"tag_weapon"))
    head.InsertUnder(root_object)
    upper.InsertUnder(root_object)
    lower.InsertUnder(root_object)
    weap.InsertUnder(root_object)
    doc.InsertObject(root_object)

def c4d_matrix_hpb(md3mat):
    v1 = c4d.Vector(md3mat[0].x, md3mat[0].y, md3mat[0].z)
    v2 = c4d.Vector(md3mat[1].x, md3mat[1].y, md3mat[1].z)
    v3 = c4d.Vector(md3mat[2].x, md3mat[2].y, md3mat[2].z)
    m = c4d.Matrix(c4d.Vector(0),v1,v2,v3)
    return c4d.utils.MatrixToHPB(m)
            
fs = QFileSystem("C:\\Program Files (x86)\\Quake III Arena")
c4d_make_player(doc, fs, "models/players/xaero", "models/weapons2/rocketl/rocketl.md3" )
#c4d_make_model(doc, fs, "models/weapons2/rocketl/rocketl.md3" )
#m = fs["models/players/xaero/lower.md3"]
#for t in m.tags:
#    print c4d_matrix_hpb(t.axis)